package lpath

import (
	"fmt"
	"strconv"
	"strings"
)

func PathExpand(expr string) ([]string, error) {
	var err error
	paths := make([]string, 1)
	// 序列开始标记;序列开始索引
	ssf, ssi := false, 0
	sc := []rune(expr)
	for i, c := range sc {
		switch c {
		case '[':
			if ssf {
				return nil, fmt.Errorf("匹配模式不能嵌套使用")
			}
			ssf = true
			ssi = i
		case ']':
			if !ssf {
				return nil, fmt.Errorf("不能单独使用']'")
			}
			ssf = false
			paths, err = expand(paths, string(sc[ssi+1:i]))
			if err != nil {
				return nil, err
			}
		default:
			if ssf {
				continue
			}
			for i, b := range paths {
				paths[i] = b + string(c)
			}
		}
	}
	if ssf {
		return nil, fmt.Errorf("不能单独使用'['")
	}
	return paths, nil

}

func expand(paths []string, s string) ([]string, error) {
	exPaths := make([]string, 0)
	subs, err := expandSub(s)
	if err != nil {
		return nil, err
	}
	for _, sub := range subs {
		for _, base := range paths {
			exPaths = append(exPaths, base+sub)
		}
	}
	if len(exPaths) > 0 {
		return exPaths, nil
	}
	return paths, nil
}

func expandSub(s string) ([]string, error) {
	subs := make([]string, 0)
	for _, sub := range strings.Split(s, ",") {
		count := strings.Count(sub, "-")
		if count == 0 {
			subs = append(subs, sub)
			continue
		}
		if count > 1 {
			return nil, fmt.Errorf("序列模式格式不正确")
		}
		seq := strings.Split(sub, "-")
		start := strings.TrimSpace(seq[0])
		end := strings.TrimSpace(seq[1])
		startNum, startErr := strconv.ParseInt(start, 10, 64)
		endNum, endErr := strconv.ParseInt(end, 10, 64)
		if startErr != nil || endErr != nil {
			return nil, fmt.Errorf("序列模式序列范围只支持数字: %s", sub)
		}
		width := len(start)
		if startNum > endNum {
			startNum, endNum = endNum, startNum
			width = len(end)
		}
		tpl := fmt.Sprintf("%%0%dd", width)
		for ; startNum <= endNum; startNum++ {
			subs = append(subs, fmt.Sprintf(tpl, startNum))
		}
	}
	return subs, nil
}

func StrListUniq(list []string) []string {
	seen := map[string]bool{}
	uniqL := make([]string, 0, len(list))
	for _, v := range list {
		if seen[v] {
			continue
		}
		uniqL = append(uniqL, v)
		seen[v] = true
	}
	return uniqL
}
